package com.yunhai.gateway.filters;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.yunhai.common.dto.GlobalException;
import com.yunhai.common.dto.Ret;
import com.yunhai.common.utils.CommonConstantUtils;
import io.jsonwebtoken.ExpiredJwtException;
import lombok.extern.slf4j.Slf4j;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.cloud.gateway.filter.GatewayFilterChain;
import org.springframework.cloud.gateway.filter.GlobalFilter;
import org.springframework.core.Ordered;
import org.springframework.core.io.buffer.DataBuffer;
import org.springframework.http.server.reactive.ServerHttpRequest;
import org.springframework.http.server.reactive.ServerHttpResponse;
import org.springframework.stereotype.Component;
import org.springframework.web.server.ServerWebExchange;
import reactor.core.publisher.Mono;

import java.nio.charset.StandardCharsets;
import java.util.Base64;
import java.util.List;

@Slf4j
@ConfigurationProperties(prefix = "spring.cloud.gateway" )
@Component
public class AuthFilter  implements GlobalFilter, Ordered {

    private List<String> whitelist;

    public void setWhitelist(List whitelist) {
        this.whitelist = whitelist;
    }

    @Override
    public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {

        //处理请求白名单
         String path = exchange.getRequest().getPath().toString();
        if( whitelist != null && whitelist.stream().anyMatch(item->path.contains(item))){
            return chain.filter(exchange);
        }

        //处理 token 不存在情形
        ServerHttpResponse serverHttpResponse = exchange.getResponse();
        String token = exchange.getRequest().getHeaders().getFirst(CommonConstantUtils.TOEKN_KEY);
        if( token == null ){
            //没有 token， 则直接 401 返回
            Ret r=  Ret.fail( 401, "用户未登录" );
            //3.4调用bufferFactory方法,生成DataBuffer对象
            DataBuffer buffer = serverHttpResponse.bufferFactory().wrap(JSON.toJSONString(r).getBytes(StandardCharsets.UTF_8));
            return serverHttpResponse.writeWith( Mono.just(buffer) );
        }

        //处理 token 非法情形
        String payload = null;
        try {

            if( token == null ){
                throw GlobalException.gen(401, "token 不存在");
            }
            String[] split = token.split("\\.");
            byte[] decode = Base64.getDecoder().decode(split[1]);
            String result = new String(decode);
            JSONObject jsonObject = JSON.parseObject(result);
            String userId =  (String)jsonObject.get("sub");
            payload = userId;
//            System.out.println("result: "+ userId);
            if( userId == null ){
              throw GlobalException.gen(401, "tokne 非法");
            }
//            Claims claims = JwtUtils.parseJWT(token);
//            payload = claims.getSubject();
//            log.info(payload+ ",token过期时间:"+claims.getExpiration().getTime()+"");
        } catch ( Exception e ){
            if( payload == null ){
                System.out.println("payload: "+ payload);
                if( e instanceof ExpiredJwtException){
                    log.error(e.getMessage());
                    //token 过期
                    return createResponse(serverHttpResponse, Ret.fail( 401, "token过期" ));
                }
                log.error(e.getMessage());
                //jwt 解析失败，则 jwt 非法， 则直接 401 返回
                return createResponse(serverHttpResponse, Ret.fail( 401, "token非法" ));
            }
        }

        ServerHttpRequest request = exchange.getRequest().mutate().header(CommonConstantUtils.JWT_TRANS_USER_INFO, payload).build();
        /**
         * 处理响应体
         * */
//        String headerKey = "aaa";
//        String headerValue = "bbb";
//        exchange.getResponse().getHeaders().add(headerKey, headerValue);
        return chain.filter(exchange);
    }

    @Override
    public int getOrder() {
        return -2;
    }

    private Mono<Void> createResponse(  ServerHttpResponse serverHttpResponse, Ret r ){
        //3.4调用bufferFactory方法,生成DataBuffer对象
        DataBuffer buffer = serverHttpResponse.bufferFactory().wrap(JSON.toJSONString(r).getBytes(StandardCharsets.UTF_8));
        return serverHttpResponse.writeWith( Mono.just(buffer) );
    }
}


